class Player:
    def __init__(self, name="界沮授"):
        """
        初始化玩家对象
        - 手牌区域：空列表
        - 装备区域：武器、防具、进攻马、防御马各区域（各至多一张）
        - 血量：初始为3，上限为4
        """
        self.name = name
        self.hand = []         # 手牌区域
        self.weapon = None     # 武器区域（至多一张）
        self.armor = None      # 防具区域（至多一张）
        self.offensive_horse = None  # 进攻马区域（至多一张）
        self.defensive_horse = None  # 防御马区域（至多一张）
        self.hp = 3            # 当前血量
        self.max_hp = 4        # 血量上限

    def draw_cards(self, cards):
        """
        摸牌：将一张或多张卡牌加入手牌区域
        :param cards: Card对象或Card对象列表
        """
        if isinstance(cards, list):
            self.hand.extend(cards)
        else:
            self.hand.append(cards)

    def is_full_health(self):
        """
        报告玩家是否满血（即当前血量是否已达到血量上限）。
        :return: 满血返回 True，否则返回 False。
        """
        return self.hp >= self.max_hp

    def equip(self, card):
        """
        统一装备接口：使用装备卡牌。
        根据卡牌类型判断：
         - 如果是武器牌，则装备到武器区；
         - 如果是防具牌，则装备到防具区；
         - 如果是进攻马牌，则装备到进攻马区；
         - 如果是防御马牌，则装备到防御马区；
        如果该卡牌不属于任何装备类别，则返回 None。
        如果该区域已有装备，则替换原装备，返回被替换的装备。
        """
        if card.is_weapon():
            return self._equip_weapon(card)
        elif card.is_armor():
            return self._equip_armor(card)
        elif card.is_offensive_horse():
            return self._equip_offensive_horse(card)
        elif card.is_defensive_horse():
            return self._equip_defensive_horse(card)
        else:
            print("该卡牌不属于任何装备类别")
            return None

    def _equip_weapon(self, card):
        old_weapon = self.weapon
        self.weapon = card
        return old_weapon

    def _equip_armor(self, card):
        old_armor = self.armor
        self.armor = card
        return old_armor

    def _equip_offensive_horse(self, card):
        old_offensive = self.offensive_horse
        self.offensive_horse = card
        return old_offensive

    def _equip_defensive_horse(self, card):
        old_defensive = self.defensive_horse
        self.defensive_horse = card
        return old_defensive

    def report_hand(self):
        """
        报告手牌：返回当前手牌区域的所有卡牌集合
        :return: 手牌列表
        """
        return self.hand
    
    def report_state(self):
        """
        报告玩家当前状态，返回一个字典，包含以下信息：
        - hand: 玩家手牌中每张牌的 card_id 列表
        - weapon: 装备在武器区的卡牌的 card_id，如果没有装备则为0
        - armor: 装备在防具区的卡牌的 card_id，如果没有装备则为0
        - offensive_horse: 装备在进攻马区的卡牌的 card_id，如果没有装备则为0
        - defensive_horse: 装备在防御马区的卡牌的 card_id，如果没有装备则为0
        - hp: 当前血量
        - max_hp: 血量上限

        这样设计后，强化学习 Agent 能够直接获取数值信息构成状态向量。
        """
        state = {
            "hand": [card.card_id for card in self.hand],
            "weapon": self.weapon.card_id if self.weapon is not None else 0,
            "armor": self.armor.card_id if self.armor is not None else 0,
            "offensive_horse": self.offensive_horse.card_id if self.offensive_horse is not None else 0,
            "defensive_horse": self.defensive_horse.card_id if self.defensive_horse is not None else 0,
            "hp": self.hp,
            "max_hp": self.max_hp
        }
        return state


    def play_card(self):
        """
        模板方法：返回玩家准备打出的卡牌。
        对外接口，无需输入参数，由游戏进程调用。
        
        返回：
            - Card对象：表示玩家选择打出的卡牌（该牌会从手牌中移除）。
            - None：表示玩家选择不出牌，也就是结束本回合。
        """
        # 1. 调用内部决策方法获得决策结果
        decision = self._make_decision()
        
        # 2. 根据决策结果处理并返回出牌内容
        card_to_play = self._process_decision(decision)
        return card_to_play

    def _make_decision(self):
        """
        玩家决策方法，负责根据当前状态选择出牌内容。
        这个方法可以作为模板方法被重载，来支持不同的决策策略。
        
        返回：
            - 一个决策结果，例如可以直接返回一个Card对象（表示选择出的牌）；
            - 或者返回 None，表示不出牌。
        """
        # 示例策略：如果手牌不为空，选择手牌中的第一张；否则返回None
        if self.hand:
            return self.hand[0]
        return None

    def _process_decision(self, decision):
        """
        根据决策结果进行处理：
          - 如果决策结果为 None，则表示玩家选择不出牌，直接返回 None；
          - 如果决策结果是一个Card对象，则从手牌中移除这张牌并返回它。
        
        参数：
            decision: _make_decision 返回的决策结果。
        
        返回：
            - Card对象：表示玩家打出的牌；
            - None：表示玩家不打出牌。
        """
        if decision is None:
            return None
        
        # 根据决策（这里假设decision是Card对象）在手牌中查找并移除对应的卡牌
        for index, card in enumerate(self.hand):
            if (card.name == decision.name and
                card.suit == decision.suit and
                card.rank == decision.rank):
                return self.hand.pop(index)
        # 若未找到对应卡牌，则返回None
        return None